#include "ScreenShot.h"

#include <QMouseEvent>
#include <QKeyEvent>
#include <QRect>
#include <QGuiApplication>
#include <QPen>
#include <QDir>
#include <QCursor>
#include <QPixmap>
#include <QScreen>
#include <QMessageBox>
#include <QDebug>
#include <QPainterPath>
#include <QPaintEvent>
#include <QPainter>


#include "ScreenShotControlWidget.h"

ScreenShot::ScreenShot(QWidget *parent)
    : QWidget{parent}
{
    setMouseTracking(true);

    //将窗口设置为无边框，透明，顶层
    setWindowFlags(Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint|Qt::Tool);
    setAttribute(Qt::WA_TranslucentBackground);
    setWindowState(Qt::WindowFullScreen);


    m_controlWidget=new ScreenShotControlWidget(this);
    m_controlWidget->hide();//先隐藏

    showFullScreen();

    connect(m_controlWidget,&ScreenShotControlWidget::CloseCapture,this,[this](){
        //关闭截屏窗口
        this->close();
    });

    ConnectSlotToControlWidget();

    //设置截图文件存储的路径，默认设置为可执行文件下的ScreenShotPicture文件夹
    QString picture_save_path=QDir::currentPath()+"/ScreenShotPicture/";
    if(!QDir(picture_save_path).exists()){
        QDir(picture_save_path).mkdir(picture_save_path);
        SetscreenShotPictureSavePath(picture_save_path);
    }
    m_screenShotSavePath=picture_save_path;

}

void ScreenShot::mouseMoveEvent(QMouseEvent *event)
{
    //鼠标移动时也同时绘制区域,cursorde setpos是全局坐标，那需要窗口坐标和全局坐标的转化
    if(m_currentStatu==CaptureStatus::Capturing){
        //只有截屏状态才能更改截屏区域
        //控制鼠标移动的区域只能在widget中
        QRect widgetRegion=this->rect();
        m_endPos=event->pos();
        if(event->pos().x()<0){
            m_endPos.setX(0);
        }
        if(event->pos().x()>this->width()){
            m_endPos.setX(this->width());
        }
        if(event->pos().y()<0){
            m_endPos.setY(0);
        }
        if(event->pos().y()>this->height()){
            m_endPos.setY(this->height());
        }
        //限制光标不超过该区域
        QCursor::setPos(mapToGlobal(m_endPos));

        update();
    }
}

void ScreenShot::mousePressEvent(QMouseEvent *event)
{
    //当鼠标按压时
    if(m_currentStatu==CaptureStatus::Default){
        //默认状态变化为截屏状态
        m_currentStatu=CaptureStatus::Capturing;
        //记录press时候的鼠标位置
        m_startPos=event->pos();
    }

}

void ScreenShot::mouseReleaseEvent(QMouseEvent *event)
{
    //鼠标释放
    if(m_currentStatu==CaptureStatus::Capturing){
        m_currentStatu=CaptureStatus::Captured;//更改状态
        m_endPos=event->pos();
        update();
        m_grapPicture=GetGrabPixmap();
        if(!m_grapPicture.isNull()){
            qDebug()<<"截图非空";
        }else{
            qDebug()<<"截图为空";
        }
        OpenControlToolBar();

        OpenDrawLabel();
        m_drawLabel->show();
        //使得drawlabel获得焦点
        m_drawLabel->raise();
        m_drawLabel->activateWindow();
    }
}

void ScreenShot::paintEvent(QPaintEvent *event)
{

    if(m_currentStatu==CaptureStatus::Default){
        //绘制全屏透明
        QPainter painter(this);
        painter.fillRect(rect(),QColor(0,0,0,30));
        return;//什么也不绘制
    }


    //只有状态为截屏状态才绘制,绘制矩形框和影罩
    if(m_currentStatu==CaptureStatus::Capturing){
        QPainter painter(this);
        QColor shadowColor=QColor(0,0,0,100);//阴影颜色
        painter.setPen(QPen(shadowColor,1,Qt::SolidLine));

        //整个遮罩区域
        QRegion maskregion(rect());
        //矩形区域
        QRegion clearregion=QRegion(QRect::span(m_startPos,m_endPos));

        //从遮罩区域减去矩形区域
        QRegion finalregion=maskregion.subtracted(clearregion);

        //将画笔的绘制区域设置为给定的finalregion
        painter.setClipRegion(finalregion);

        //整个区域设置为灰色
        painter.fillRect(rect(),shadowColor);
    }


    //除了阴影什么也不绘制
    if(m_currentStatu==CaptureStatus::Captured){
        //矩形选区结束

        QPainter painter(this);
        QColor shadowColor=QColor(0,0,0,100);//阴影颜色
        painter.setPen(QPen(shadowColor,1,Qt::SolidLine));

        //整个遮罩区域
        QRegion maskregion(rect());
        //矩形区域
        QRegion clearregion=QRegion(QRect::span(m_startPos,m_endPos));

        //从遮罩区域减去矩形区域
        QRegion finalregion=maskregion.subtracted(clearregion);

        //将画笔的绘制区域设置为给定的finalregion
        painter.setClipRegion(finalregion);

        //整个区域设置为灰色
        painter.fillRect(rect(),shadowColor);
    }

}

void ScreenShot::keyPressEvent(QKeyEvent *event)
{
    if(event->key()==Qt::Key_Escape){
        this->close();
        update();
    }
}


QPixmap ScreenShot::GetGrabPixmap()
{
    //根据当前窗口获取所在的屏幕
    QScreen *screen = this->screen();

    //屏幕缩放倍数
    qreal scaleFactor=screen->devicePixelRatio();

    QPoint screen_topleft=screen->geometry().topLeft();
    //截取这个屏幕
    QPixmap originalPixmap;
    if(screen!=nullptr){
        originalPixmap= screen->grabWindow(0);
    }

    QPoint left_top,right_botton;
    left_top=screen->geometry().topLeft();
    right_botton=screen->geometry().bottomRight();

    //起终点的全局坐标
    QPoint p1(mapToGlobal(m_startPos));
    QPoint p2(mapToGlobal(m_endPos));

    if(screen->geometry().topLeft().x()!=0&&screen->geometry().topLeft().y()!=0){
        //副屏
        //找到截取区域的相对位置
        p1=QPoint(p1.x()-screen_topleft.x(),p1.y()-screen_topleft.y());
        p2=QPoint(p2.x()-screen_topleft.x(),p2.y()-screen_topleft.y());
        p1=p1*scaleFactor;
        p2=p2*scaleFactor;
        return originalPixmap.copy(QRect::span(p1,p2));
    }else{
        //主屏
        p1=p1*scaleFactor;
        p2=p2*scaleFactor;
        return originalPixmap.copy(QRect::span(p1,p2));
    }
}

QPixmap ScreenShot::GetFinalGrabPixmap() const
{
 return m_grapPicture;
}

void ScreenShot::SetscreenShotPictureSavePath(const QString path)
{
    m_screenShotSavePath=path;
}



void ScreenShot::OpenControlToolBar()
{
    qreal scalefactor=this->screen()->devicePixelRatio();

    //不包含缩放因子的
    QSize widgetSize=this->size();
    QSize controlwdigetSize=m_controlWidget->size();

    //截屏区域的右下角坐标
    QRect rect=QRect::span(m_startPos,m_endPos);
    QPoint rect_rightbotton=rect.bottomRight();

    //控制窗口的两个窗口的高度和（逻辑坐标）
    int controlwidget_height=(m_controlWidget->height()+m_controlWidget->m_casualDrawWidgetContainer->height());

    //计算下方的可用空间(整个屏幕高度-截屏区域高度y)全局-全局
    int allowHeight=widgetSize.height()-rect_rightbotton.y();

    int x=(rect_rightbotton.x()-(m_controlWidget->width()));
    int y;

    if(allowHeight>=controlwidget_height){
        y=rect_rightbotton.y();
    }else{
        y=rect_rightbotton.y()-controlwidget_height ;
    }

    QPoint targetPos=QPoint(x,y);
    m_controlWidget->move(mapToGlobal(targetPos));
    m_controlWidget->show();
}

void ScreenShot::OpenDrawLabel()
{
    //这个p1,p2是没有乘以系数的
    QPoint p1(mapToGlobal(m_startPos));
    QPoint p2(mapToGlobal(m_endPos));

    m_drawLabel=new DrawLabel(this,QRect::span(p1,p2));
    //将截取到的图像传递过去作为最底部的画板绘制
    m_drawLabel->m_canvas=m_grapPicture;
    m_drawLabel->hide();

    QRect rect=QRect::span(p1,p2);

    //将m_drawlabel移至父对象的这个位置
    m_drawLabel->setGeometry(QRect::span(m_startPos,m_endPos));
    // m_drawLabel->setFixedSize(rect.size());
}

void ScreenShot::ConnectSlotToControlWidget()
{
    //触发画板的保存按钮
    QObject::connect(m_controlWidget,&ScreenShotControlWidget::SaveCapture,[this](){

        //直接get会存在一个问题，最新键入的字符没法打印
        m_grapPicture=m_drawLabel->GetCanva();

        emit VerifyScreenShotPicture();
    });

    //那边图片保存完毕后将截图窗口关闭
    QObject::connect(this,&ScreenShot::CloseScreenShotWidget,this,[this](){
        qDebug()<<"emit CloseSCreenCaptureWidget信号";
         m_controlWidget->close();
         this->close();
        update();
        this->deleteLater();
    });

    //改变画笔颜色和画笔大小的信号槽
    QObject::connect(m_controlWidget,&ScreenShotControlWidget::ChangePen,[this](){
        //触发画板的修改颜色槽函数,获取当前的画笔pen,传进drawlabel中当作label的画笔
        QPen pen=m_controlWidget->GetPen();
        this->m_drawLabel->ChangePen(pen);
    });

    //改变为绘制矩形的信号槽
    connect(m_controlWidget,&ScreenShotControlWidget::DrawRect,[this](){
        m_drawLabel->DrawRect();
    });

    //改变为绘制椭圆的信号槽
    connect(m_controlWidget,&ScreenShotControlWidget::DrawEllipse,[this](){
        m_drawLabel->DrawEllipse();
    });

    //改变为绘制箭头的信号槽
    connect(m_controlWidget,&ScreenShotControlWidget::DrawArrow,[this](){
        //改变状态，函数在paintevent中调用
        m_drawLabel->m_curDrawType=DrawLabel::DrawType::Arrow;
    });

    //改变为随意绘制的信号槽
    connect(m_controlWidget,&ScreenShotControlWidget::DrawCasual,[this](){
        //改变状态
        m_drawLabel->m_curDrawType=DrawLabel::DrawType::CasualDraw;
        m_drawLabel->DrawCasual();
    });

    //改变为绘制文本的信号槽
    connect(m_controlWidget,&ScreenShotControlWidget::DrawText,[this](){
        m_drawLabel->m_curDrawType=DrawLabel::DrawType::Text;
    });

    connect(m_controlWidget,&ScreenShotControlWidget::ComeBack,[this](){
        m_drawLabel->ComeBack();
    });
}
